<?php
use oxide\http\Request;
use oxide\http\Response;
use oxide\data\Connection;

require_once APP_DIR . '/library/Command.php';
require_once LIB_DIR . '/oxide/Connection.php';
require_once APP_DIR . '/library/DataModel.php';

/**
 * Action Controller
 *
 * Action controller is the primary controller for MVC design pattern
 * All application specific controllers will usually extends this controller
 * 
 * @package yasns
 * @subpackage library
 * @filesource
 */
class ActionController implements Command
{
	private
		$_request,
		$_response,
		$_controller,
		$_action,
		$_connection;
	
	protected 
	  $_viewScript,
	  $_layoutScript;



	/**
	 * initialize the controller
	 * 
	 * initial set up of request, response, action, and the database
	 *
	 * @param oxide\http\Request $request
	 * @param oxide\http\Response $response
	 * @param string $action 
	 */
	public function __construct($request, $response, $controller, $action)
	{
		$viewdir = APP_DIR . '/view';
		$layoutdir = ROOT_DIR . '/template';
		
		// stores all variables in object scope
		$this->_request = $request;
		$this->_response = $response;
		$this->_controller = strtolower($controller);
		$this->_action = strtolower($action);
		
		// generate and store view script and layout script
		$this->_viewScript = "{$viewdir}/{$this->_controller}/{$this->_action}.html";
		$this->_layoutScript = "{$layoutdir}/layout.html";
		
		// setting the database configs
		$dbconfig = array(
			 'driver'      => 'mysql',
			 'host'        => 'localhost',
			 'username'    => 'root',
			 'password'    => 'playground7BNIaj1x2',
			 'catalog'     => 'yasns_db',
		);
		
		$dboptions = array(
				\PDO::ATTR_ERRMODE	=> \PDO::ERRMODE_EXCEPTION,
				'FETCH_MODE'			=> \PDO::FETCH_ASSOC
				);
		
		$this->_connection = new Connection($dbconfig,$dboptions);
		\DataModel::setConnection($this->_connection);
	}
	
	/**
	 * get the view script for the current action
	 * 
	 * @access public
	 * @return string
	 */
	public function getViewScript()
	{
		return $this->_viewScript;
	}
	
	/**
	 * get the layout script
	 * 
	 * @access public
	 * @return string
	 */
	public function getLayoutScript()
	{
		return $this->_layoutScript;
	}
	
	
	/**
	 * Retrieve the existing database connection
	 * 
	 * @access public
	 * @return oxide\data\Connection
	 */
	public function getConnection()
	{
		return $this->_connection;
	}
	
	/**
	 * implement Command interface and design pattern
	 *
	 * This is the main function that executes user action and renders view
     * Action to execute will be generated based on url.
     * for example if user enters http://domain.com/{controller}/{action}
     * then execute{Action}() will be executed
	 * 
	 * @access public
	 */
	public function execute() 
	{   
		// generate the action method     
		$method = "execute" . ucfirst($this->_action);
		
		// first make sure we have action implemented
		if(!method_exists($this, $method)) {
			// if action method does not exist,
			// this is same as page not found error
			throw new Exception("Page not found", 404);
		}
		
		$this->$method();
		$this->render();
	}

	/**
	 * render view based on the view files
	 * 
	 * Will render both action view and layout view
	 * @access public
	 */
	public function render()
	{
		$vscript = $this->getViewScript();
		$lscript = $this->getLayoutScript();
		
		// rendering the view script
		ob_start();
		include $vscript;
		$this->VIEW_CONTENT = ob_get_clean();
		
		// rendering the layout script
		include $lscript;
	}
	
	/**
	 * retrieve request, response, action based on the requested actionController file
	 * 
	 * @param oxide\http\Request $request
	 * @param oxide\http\Response $response
	 * @return ActionController
	 */
	public static function make($request, $response)
	{
		$controller = ucfirst(strtolower($request->getPathAtIndex(0)));
		$action = strtolower(trim($request->getPathAtIndex(1)));
      
      if(empty($action)) {
         $action = 'index';
      }
      
      if(empty($controller)) {
         $controller = 'Default';
      }
      
		$class = "{$controller}ActionController";
		$file = APP_DIR . "/controller/{$class}.php";
		require_once $file;
		$object = new $class($request, $response, $controller, $action);
		
		return $object;
	}
}
?>
